#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include "EquationSolver.h"

using namespace std;

class func: public Function
{
    public:
        double l,h,D,beta;
        double A = l*sin(beta);
        double B = l*cos(beta);
        double C = (h+0.5*D)*sin(beta)-0.5*D*tan(beta);
        double E = (h+0.5*D)*cos(beta)-0.5*D;

        func(double l, double h, double D, double beta):l(l), h(h), D(D), beta(beta){};
        double get_value(double x){
            double val = A*sin(x)*cos(x) + B*sin(x)*sin(x) - C*cos(x) - E*sin(x);
            return val;
        }
        /*double get_derivation(double x){
            double der = A*(cos(x)*cos(x)-sin(x)*sin(x)) + 2*B*sin(x)*cos(x) + C*sin(x) - E*cos(x);
            return der;
        }*/
};

int main()
{
    double e = 1e-8;
    double d = 1e-8;
    double m = 50;

    Newton new_solver(e, m);
    Secant sec_solver(e, d, m);

    func f1(89, 49, 55, 11.5/180*M_PI);
    InitInput input1(f1);
    input1.setNewtonInput(33.0/180*M_PI);
    double alpha1 = new_solver.solve(input1);
    cout << "(a) alpha = " << alpha1 << " (with val " << f1.get_value(alpha1) << ")" << endl;

    func f2(89, 49, 30, 11.5/180*M_PI);
    InitInput input2(f2);
    input2.setNewtonInput(33.0/180*M_PI);
    double alpha2 = new_solver.solve(input2);
    cout << "(b) alpha = " << alpha2 << " (with val " << f2.get_value(alpha2) << ")" << endl;

    InitInput input3(f1);
    input3.setSecantInput(33.0, 31.0);
    double alpha3 = sec_solver.solve(input3);
    cout << "(c) x1 = 31, alpha = " << alpha3 << " (with val " << f1.get_value(alpha3) << ")" << endl;
    input3.setSecantInput(33.0, 30.0);
    alpha3 = sec_solver.solve(input3);
    cout << "(c) x1 = 30, alpha = " << alpha3 << " (with val " << f1.get_value(alpha3) << ")" << endl;
    input3.setSecantInput(33.0, 16.0);
    alpha3 = sec_solver.solve(input3);
    cout << "(c) x1 = 16, alpha = " << alpha3 << " (with val " << f1.get_value(alpha3) << ")" << endl;
    input3.setSecantInput(33.0, 3.0);
    alpha3 = sec_solver.solve(input3);
    cout << "(c) x1 = 3, alpha = " << alpha3 << " (with val " << f1.get_value(alpha3) << ")" << endl;

    return 0;
}